import { Injectable, Inject, BadRequestException } from '@nestjs/common';
import { Schema } from 'mongoose';

import { BlogModel, DictionaryModel } from '@server/models';
import { AuthService } from '@server/auth';
import { BaseResponse } from '@server/basic-dto';
import { DIC_TYPE_CODE_NOT_EXIST } from '@server/modules/dictionary/error';

import { CreateOrUpdateBlogDto, BlogDetailResponse, BlogListResponse, BlogHomeResponse } from './dto';

@Injectable()
export default class BlogService {
  constructor(
    private readonly authService: AuthService,
    @Inject('BLOG_MODEL') private readonly blogModel: typeof BlogModel,
    @Inject('DICTIONARY_MODEL')
    private readonly dictionaryModel: typeof DictionaryModel,
  ) {}

  async create(
    createBlog: CreateOrUpdateBlogDto,
    token: string,
  ): Promise<BaseResponse> {
    const count: number = await this.dictionaryModel.countDocuments({
      _id: createBlog.locale,
    });

    if (count === 0) {
      throw new BadRequestException(DIC_TYPE_CODE_NOT_EXIST);
    }

    const { id: creator } = this.authService.parse(token);
    await this.blogModel.create(Object.assign({}, createBlog, { creator }));

    return {
      code: 0,
      message: '',
    };
  }

  async update(
    id: string,
    updateBlog: CreateOrUpdateBlogDto,
  ): Promise<BaseResponse> {
    await this.blogModel.findByIdAndUpdate(id, updateBlog);

    return {
      code: 0,
      message: '',
    };
  }

  async toggle(id: string, state: string | number): Promise<BaseResponse>{
    state = parseInt(`${state}`)
    const update: {
      state: number;
      publishedAt?: Number;
    } = {
      state
    };

    if (state === 1) {
      update.publishedAt = Date.now()
    }
    await this.blogModel.findByIdAndUpdate(id, update);

    return {
      code: 0,
      message: '',
    };
  }

  async delete(ids: string): Promise<BaseResponse> {
    const idsArr: Array<string> = ids.split(',');

    for (const id of idsArr) {
      await this.blogModel.findByIdAndRemove(id);
    }

    return {
      code: 0,
      message: '',
    };
  }

  async list(page: number = 1, pageSize: number = 10, keyword: string = '', locale: string): Promise<BlogListResponse> {
    const query: {
      locale?: string;
      title?: {
        $regex: string;
        $options: string;
      }
    } = {};

    if (locale) {
      query.locale = locale;
    }

    if (keyword) {
      query.title = {
        $regex: keyword,
        $options: '$i'
      };
    }

    const data: any = await this.blogModel.paginate({
      query,
      page: parseInt(`${page}`),
      limit: parseInt(`${pageSize}`),
    });

    return {
      code: 0,
      message: '',
      data,
    };
  }

  async frontlist(page: number = 1, pageSize: number = 10, keyword: string = '', locale: string): Promise<BlogListResponse> {
    const query: {
      locale: string;
      state: number;
      title?: {
        $regex: string;
        $options: string;
      }
    } = {
      locale,
      state: 1
    };

    if (keyword) {
      query.title = {
        $regex: keyword,
        $options: '$i'
      };
    }

    const data: any = await this.blogModel.paginate({
      query,
      page: parseInt(`${page}`),
      limit: parseInt(`${pageSize}`),
    });

    return {
      code: 0,
      message: '',
      data,
    };
  }

  async homelist(locale: string): Promise<BlogHomeResponse> {
    const data: any = await this.blogModel.find({
      locale,
      state: 1
    });

    return {
      code: 0,
      message: '',
      data
    }
  }

  async detail(id: string, isFront: boolean = false): Promise<BlogDetailResponse> {
    let data;
    if (isFront) {
      data = await this.blogModel.findByIdAndUpdate(id, {
        $inc: {
          readCount: 1
        }
      });
    } else {
      data = await this.blogModel.findById(id);
    }

    return {
      code: 0,
      message: '',
      data,
    };
  }
}
